<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Ace</title>


<script src="../ace/build/src/ace-uncompressed.js" type="text/javascript" charset="utf-8"></script>
<script src="../ace/build/src/theme-clouds.js" type="text/javascript" charset="utf-8"></script>
<script src="../ace/build/src/mode-sql.js" type="text/javascript" charset="utf-8"></script>
<script src="../dslparser/parser.js" type="text/javascript" charset="utf-8"></script>
<script src="../jsDump.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8" src="../jquery-1.7.js"></script>
<script type="text/javascript" charset="utf-8" src='autocomplete.js'></script>
<link type="text/css" href="../css/ui-lightness/jquery-ui-1.8.16.custom.css" rel="stylesheet"/>
<link type="text/css" href="../css/style.css" rel="stylesheet"/>
<script type="text/javascript" src="../jquery-ui-1.8.16.custom.min.js"></script>

<script type="text/javascript">

var editor;

var autocompleting = false;
var auto;
const tupleRegex = new RegExp("\(('[a-zA-Z0-9\s]')(,'[a-zA-Z0-9\s]')*\)", 'g');
const stringRegex = new RegExp("'[a-zA-Z0-9\s]*'", 'g');
const numberRegex = new RegExp("[0-9]*(,[0-9]*)?", 'g');
const dateRegex = new RegExp("[0-9][1-9]\/[0-9][1-9]\/[0-9][1-9]([0-9][0-9])?", 'g');

const tokenRegexArray = [tupleRegex,stringRegex,dateRegex,numberRegex];

window.onload = function() {
    editor = ace.edit("editor");

    //editor.getSession().setUseWrapMode(true);
    editor.setTheme("ace/theme/clouds");
    var Mode = require("ace/mode/sql").Mode;
    var Autocomplete = require('globalmaksimum/autocomplete').Autocomplete;
    var timer = null;
    var variableOptions = ['city','team','school','age','startDate'];
    auto = new Autocomplete(editor);
    var Range = require('ace/range').Range;
    editor.getSession().setMode(new Mode());

    editor.setBehavioursEnabled(false);

    editor.commands.addCommand({
        name: "inserttext",
        exec: function(editor, args, request) {
            var lang = require("ace/lib/lang");

            editor.insert(lang.stringRepeat(args.text || "", args.times || 1));

            if (autocompleting) {

                var command = editor.commands.commands['autocomplete'];

                command.exec(editor);
            }
        }
    });
    editor.commands.addCommand({
        name: "triggerAutocomplete",
        bindKey: {
            win: "Ctrl-Space",
            mac: "Ctrl-Space",
            sender: "editor"
        },
        exec: function(editor, args, request) {
            setTimeout(function() {
                generateAdvice(AdviceOn.COMMAND);
            }, 0);
        }
    });

    function isEndOfDocument() {
        var cursorPosition = editor.getCursorPosition();
        var documentLastRow = editor.getSession().getDocument().getLength() - 1;
        var documentLastColumn = editor.getSession().getDocument().getLine(documentLastRow).length;
        if (cursorPosition.row == documentLastRow && cursorPosition.column == documentLastColumn)
            return true;
        return false;
    }

    var AdviceOn = {
        INPUT:1,
        CURSOR:2,
        COMMAND:3
    };

    function generateAdvice(adviceOn) {
        var editorValue = editor.getSession().getValue();
        if (showAdvice(adviceOn)) {
            var parseValue = null;
            if (adviceOn == AdviceOn.COMMAND) {
                var cursor = editor.getCursorPosition();
                parseValue = editor.getSession().getTextRange(new Range(0, 0, cursor.row, cursor.column));
            } else
                parseValue = editorValue;
            console.log(parseValue);
            try {

                var result = dslparser.parse(parseValue, "start", true);
                try {
                    dslparser.parse(editorValue + ' a');
                } catch(e) {
                    showParserRecommendations(e);
                }

            } catch(e) {
                //we are at the end of document and parsing failed show recommendation
                // Make line red
                console.log(e.line);
                if (!e.line) {
                    console.log('undefined line');
                } else
                    $('#editor .ace_text-layer .ace_line:nth-child(' + e.line + ')').toggleClass('syntax_error');
                if (adviceOn == AdviceOn.INPUT || isEndOfDocument())
                    showParserRecommendations(e);
                else
                    showContextRecommendations(e);
            }
        }
    }

    function showAdvice(adviceOn) {
        return adviceOn == AdviceOn.COMMAND || (adviceOn == AdviceOn.INPUT && isEndOfDocument());
    }

    function preparefailuresExpected(error) {
        error.rightmostMatchFailuresExpected.sort();

        var lastFailure = null;
        var failuresExpectedUnique = [];
        for (var i = 0; i < error.rightmostMatchFailuresExpected.length; i++) {
            if (error.rightmostMatchFailuresExpected[i] !== lastFailure
                    && error.rightmostMatchFailuresExpected[i] != '" "'
                    && error.rightmostMatchFailuresExpected[i] != '"\\n"') {
                failuresExpectedUnique.push(error.rightmostMatchFailuresExpected[i]);
                lastFailure = error.rightmostMatchFailuresExpected[i];
            }
        }
        return failuresExpectedUnique;
    }

    function showParserRecommendations(error) {
        var failuresExpectedUnique = preparefailuresExpected(error);
        if ($.inArray('variable', failuresExpectedUnique) != -1) {
            //get all the variables and show recommedations
            var range = editor.getSelectionRange();
            var cursor = editor.getCursorPosition();
            var range = editor.getSession().getWordRange(cursor.row, cursor.column);
            if (range.start.row <= error.line - 1 && range.end.row >= error.line - 1
                    && range.start.column <= error.column - 1 && range.end.column >= error.column - 1) {

                //var keywordColumn = keywordRange.end.column;
                auto.activate(error.line - 1, error.column - 1);
                auto.suggest('', variableOptions);
            }
        } else if ($.inArray('tuple', failuresExpectedUnique) != -1) {
            //show tupple completation
            console.log('tuple recommendation');
        } else {
            var result = [];
            $.each(failuresExpectedUnique, function(index, value) {
                result.push(value.replace(/"/g, ''));
            });
            if (result.length > 0) {
                auto.activate(error.line - 1, error.column - 1);
                auto.suggest('', result);
            } else {
                console.log('content assist notavailable');
            }
        }

    }

    function showContextRecommendations(error) {

        var cursor = editor.getCursorPosition();
        var cursorLine=editor.getLine(cursor.row);
        for(var i in tokenRegexArray){
            var matches=cursorLine.match(tokenRegexArray[i]);
            if(matches){
                var startIndex=0;
                for(var j in matches){
                    var start = cursorLine.indexOf(matches[j],startIndex);
                    var end = start+matches[j].length;
                    if(cursor.)
                }
            }
        }
    }

    function scheduleAdviceGenerator(advice) {
        timer = setTimeout(function() {
            generateAdvice(advice);
            timer = null;
        }, 300);
    }

    function triggerChange(advice) {
        //TODO:do we have to clear red line here or after parsing
        $('#editor .ace_text-layer .ace_line').toggleClass('syntax_error', false);

        if (timer == null) {
            scheduleAdviceGenerator(advice);
        } else {
            clearTimeout(timer);
            scheduleAdviceGenerator(advice);
        }
    }

    function getWordRange(row, column) {
        var cursor = this.getCursor();
        var line = this.getLine(row);

        var inToken = false;
        if (column > 0) {
            inToken = !!line.charAt(column - 1).match(this.tokenRe);
        }

        if (!inToken) {
            inToken = !!line.charAt(column).match(this.tokenRe);
        }

        var re = inToken ? this.tokenRe : this.nonTokenRe;

        var start = column;
        if (start > 0) {
            do {
                start--;
            }
            while (start >= 0 && line.charAt(start).match(re));
            start++;
        }

        var end = column;
        while (end < line.length && line.charAt(end).match(re)) {
            end++;
        }

        return new Range(row, start, row, end);
    }

    function isStringLiteral(line, row, column) {
        var literalArray = line.match(literalSearch);
        for (var i in literalArray) {
            var start = line.indexOf(literalArray[i]);
            var end = start + literalArray[i].length;
        }
    }

    editor.getSession().addEventListener('change', function(oldRange, newRange, newText) {
        triggerChange(AdviceOn.INPUT);
    });
    editor.getSession().selection.on('changeCursor', function(oldRange, newRange, newText) {
        triggerChange(AdviceOn.CURSOR);
    });

};
</script>

</head>

<body>


<h1>Autocomplete Demo</h1>

<p>Try pressing &lt;</p>

<div id="editor" style="width:800px; height:400px; font-size:12px;"></div>


<br/>
<br/>
<br/>
<br/>

</body>
</html>

